package com.qihoo.mm.camera.collage.template.ui.view;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;

import seekting.demo2017.AppEnv;

/**
 * Created by seekting on 17-5-16.
 */

public class CollageLayout extends ViewGroup {
    public static final boolean DEBUG = AppEnv.bAppdebug;
    public static final String TAG = "TemplateWorkSpace";
    private float mWorkSpaceWidthDp;
    private float mWorkSpaceHeightDp;
    /**
     * width/widthDp=zoom;
     */
    private float mWorkSpaceZoom;

    private float density;

    /**
     * 自己的实际宽度太窄
     */
    private boolean mIsWidthTooNarrow;

    private Map<View, Rect> mViewRectMap = new HashMap<>();
    private Map<View, Rect> mSelectRectMap = new HashMap<>();
    private ArrayList<View> mMeasuredViews = new ArrayList<>();

    private static final Comparator COMPARATOR = new Comparator<View>() {
        @Override
        public int compare(View lhs, View rhs) {
            LayoutParams left = (LayoutParams) lhs.getLayoutParams();
            LayoutParams right = (LayoutParams) rhs.getLayoutParams();
            return left.zOrder - right.zOrder;
        }
    };

    public void setExpectSpace(float workSpaceWidthDp, float workSpaceHeightDp) {
        mWorkSpaceWidthDp = workSpaceWidthDp;
        mWorkSpaceHeightDp = workSpaceHeightDp;
    }


    public float getWorkSpaceZoom() {
        return mWorkSpaceZoom;
    }


    public CollageLayout(Context context) {
        super(context);

        init();
    }


    public CollageLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    private void init() {
        density = getResources().getDisplayMetrics().density;
        setChildrenDrawingOrderEnabled(true);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int maxWidth = MeasureSpec.getSize(widthMeasureSpec);
        int maxHeight = MeasureSpec.getSize(heightMeasureSpec);
        if (maxWidth == 0 || maxHeight == 0) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            return;
        }
        if (mWorkSpaceWidthDp == 0 || mWorkSpaceHeightDp == 0) {

            throw new RuntimeException("mWorkSpaceWidthDp或mWorkSpaceHeightDp必需都不为0!");
        }
        int targetWidth = Math.round(density * mWorkSpaceWidthDp);
        int targetHeight = Math.round(density * mWorkSpaceHeightDp);

        float widthZoom = maxWidth / mWorkSpaceWidthDp;
        float heightZoom = maxHeight / mWorkSpaceHeightDp;
        mIsWidthTooNarrow = widthZoom < heightZoom;
        int measuredWidth = 0;
        int measuredHeight = 0;
        //以宽为最大基准
        if (mIsWidthTooNarrow) {
            measuredWidth = maxWidth;
            measuredHeight = Math.round(mWorkSpaceHeightDp * widthZoom);
            mWorkSpaceZoom = widthZoom;
            if (DEBUG) {
                Log.d(TAG, "onMeasure.宽度不足!以宽适配高");
            }
        } else {
            measuredWidth = Math.round(mWorkSpaceWidthDp * heightZoom);
            measuredHeight = maxHeight;
            mWorkSpaceZoom = heightZoom;
            if (DEBUG) {
                Log.d(TAG, "onMeasure.高度不足!以高适配宽");
            }
        }

        if (DEBUG) {
            Log.d(TAG, "onMeasure.期望的宽高为:" + mWorkSpaceWidthDp + ":" + mWorkSpaceHeightDp);
            Log.d(TAG, "onMeasure.最终的宽高为:" + measuredWidth + ":" + measuredHeight);
        }
        setMeasuredDimension(measuredWidth, measuredHeight);


        mMeasuredViews.clear();
        mViewRectMap.clear();
        mSelectRectMap.clear();

        int count = getChildCount();
        for (int i = 0; i < count; i++) {
            View child = getChildAt(i);
            LayoutParams layoutParams = (LayoutParams) child.getLayoutParams();
            Rect rect = new Rect();
            rect.left = Math.round(layoutParams.expectLeft * mWorkSpaceZoom);
            rect.right = Math.round(layoutParams.expectRight * mWorkSpaceZoom);
            rect.top = Math.round(layoutParams.expectTop * mWorkSpaceZoom);
            rect.bottom = Math.round(layoutParams.expectBottom * mWorkSpaceZoom);
            int childWidth = rect.width();
            int childHeight = rect.height();
            child.measure(MeasureSpec.makeMeasureSpec(childWidth, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(childHeight, MeasureSpec.EXACTLY));
            mMeasuredViews.add(child);
            mViewRectMap.put(child, rect);
            child.setRotation(layoutParams.rotate);


        }
        Collections.sort(mMeasuredViews, COMPARATOR);


    }


    protected LayoutParams generateDefaultLayoutParams() {
        return new LayoutParams(0, 0, 10, 10, 0, 0);
    }

    @Override
    protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
        return p instanceof LayoutParams;
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {

        if (DEBUG) {
            Log.d(TAG, "onLayout.r=" + r + ",b=" + b + "t=" + t);
        }

        int count = getChildCount();
        for (int i = 0; i < count; i++) {
            View measuredView = getChildAt(i);
            Rect rect = mViewRectMap.get(measuredView);
            measuredView.layout(rect.left, rect.top, rect.right, rect.bottom);
        }

    }

    @Override
    protected int getChildDrawingOrder(int childCount, int i) {
        int order = mMeasuredViews.indexOf(getChildAt(i));
        return order;

    }


    /**
     * mWorkSpaceWidthDp * density
     *
     * @param v
     * @param outPx
     * @return
     */
    public static Bitmap screenShort(View v, float outPx) {
        Bitmap result = null;
        Bitmap bitmap = null;
        try {
            v.setDrawingCacheEnabled(true);
            bitmap = v.getDrawingCache();


        } catch (Throwable t) {
            if (DEBUG) {
                Log.e(TAG, "screenShort.", t);
            }
        }
        if (bitmap != null) {
            Matrix matrix = new Matrix();

            float scale = outPx / bitmap.getWidth();
            while (result == null) {
                matrix.reset();
                matrix.postScale(scale, scale);
                try {
                    result = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
                } catch (Throwable t) {
                    if (DEBUG) {
                        Log.e(TAG, "screenShort.", t);
                    }

                }
                scale = scale / 2f;
            }
        }
        if (v.isDrawingCacheEnabled()) {
            v.setDrawingCacheEnabled(false);
        }
        return result;

    }


    public static class LayoutParams extends ViewGroup.LayoutParams {
        float expectLeft, expectTop, expectRight, expectBottom;
        public int zOrder;
        public float rotate;


        public LayoutParams(float expectLeft, float expectTop, float expectRight, float expectBottom, int zOrder, float rotate) {
            super(0, 0);
            this.expectLeft = expectLeft;
            this.expectTop = expectTop;
            this.expectRight = expectRight;
            this.expectBottom = expectBottom;
            this.rotate = rotate;
            this.zOrder = zOrder;
        }


        public LayoutParams(Context c, AttributeSet attrs) {
            super(c, attrs);
        }
    }
}
